/*
 * Copyright © 2025 秋辞未寒 (545073804@qq.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gitee.colordreams.mapstruct.convert.mapper;

import org.mapstruct.MappingTarget;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * BeanCopyMapper接口
 *
 * @param <T> Bean Type
 * @author 秋辞未寒
 */
public interface BeanCopyMapper<T> extends MapperAware {

    /**
     * 拷贝对象
     *
     * @param bean 对象
     * @return 拷贝对象
     */
    T copy(T bean);

    /**
     * 拷贝对象
     *
     * @return 拷贝对象函数
     */
    default Function<T, T> copyFunction() {
        return this::copy;
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param bean  对象
     * @param after 拷贝后操作
     * @return 目标对象
     */
    default T copy(T bean, Consumer<T> after) {
        T targetBean = copy(bean);
        after.accept(targetBean);
        return targetBean;
    }

    /**
     * 拷贝对象
     *
     * @param after 拷贝后操作
     * @return 拷贝对象函数
     */
    default Function<T, T> copyFunction(Consumer<T> after) {
        return bean -> copy(bean, after);
    }

    /**
     * 拷贝对象
     *
     * @param bean       对象
     * @param targetBean 拷贝后的目标对象
     */
    void copy(T bean, @MappingTarget T targetBean);

    /**
     * 拷贝对象
     *
     * @param targetBean 拷贝后的目标对象
     * @return 拷贝对象函数
     */
    default Function<T, T> copyFunction(T targetBean) {
        return bean -> {
            copy(bean, targetBean);
            return targetBean;
        };
    }

    /**
     * 将源对象转换为目标对象
     *
     * @param bean  对象
     * @param after 拷贝后操作
     */
    default void copy(T bean, T targetBean, Consumer<T> after) {
        copy(bean, targetBean);
        after.accept(targetBean);
    }

    /**
     * 拷贝对象
     *
     * @param targetBean 拷贝后的目标对象
     * @param after      拷贝后操作
     * @return 拷贝对象函数
     */
    default Function<T, T> copyFunction(T targetBean, Consumer<T> after) {
        return bean -> {
            copy(bean, targetBean, after);
            return targetBean;
        };
    }

    /**
     * 批量拷贝对象
     *
     * @param beans 对象列表
     * @return 拷贝对象列表
     */
    default List<T> copyList(List<T> beans) {
        return beans.stream()
                .map(this::copy)
                .collect(Collectors.toList());
    }

    /**
     * 批量拷贝对象
     *
     * @return 拷贝对象函数
     */
    default Function<List<T>, List<T>> copyListFunction() {
        return this::copyList;
    }

    /**
     * 批量拷贝对象
     *
     * @param beans     对象列表
     * @param eachAfter 每一个元素拷贝后操作
     * @return 拷贝对象列表
     */
    default List<T> copyList(List<T> beans, Consumer<T> eachAfter) {
        if (eachAfter == null) {
            return copyList(beans);
        }
        return beans.stream()
                .map(bean -> copy(bean, eachAfter))
                .collect(Collectors.toList());
    }

    /**
     * 批量拷贝对象
     *
     * @param eachAfter 每一个元素拷贝后操作
     * @return 拷贝对象函数
     */
    default Function<List<T>, List<T>> copyListFunction(Consumer<T> eachAfter) {
        return beans -> copyList(beans, eachAfter);
    }

    /**
     * 批量拷贝对象
     *
     * @param beans     对象列表
     * @param listAfter 对象列表拷贝后操作
     * @return 拷贝对象列表
     */
    default List<T> copyListAll(List<T> beans, Consumer<List<T>> listAfter) {
        List<T> targetBeans = copyList(beans);
        if (listAfter != null && targetBeans != null) {
            listAfter.accept(targetBeans);
        }
        return targetBeans;
    }

    /**
     * 批量拷贝对象
     *
     * @param listAfter 对象列表拷贝后操作
     * @return 拷贝对象函数
     */
    default Function<List<T>, List<T>> copyListAllFunction(Consumer<List<T>> listAfter) {
        return beans -> copyListAll(beans, listAfter);
    }

}
